package com.zx.mes.senior.concurrent;

import lombok.extern.slf4j.Slf4j;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author huayunlong
 * @date 2018-9-6
 */
@Slf4j
public class CurrentTest {
    public static final int INT = 1000;
    ThreadPoolExecutor executor;
    AtomicInteger integer = new AtomicInteger(0);
    AtomicReference<Integer> reference = new AtomicReference<>(0);

    Integer count = 0;

    @Before
    public void before() {

        int processors = Runtime.getRuntime().availableProcessors();
        executor = new ThreadPoolExecutor(processors / 3 + 1,
                processors + 1,
                120,
                TimeUnit.SECONDS, new ArrayBlockingQueue<>(200), r -> {
            Thread thread = new Thread(r);
            thread.setName("threadPool thread");
            return thread;
        });
    }

    @After
    public void after() {
        executor.shutdown();
    }

    /**
     * 5000次 100个线程执行
     * 执行log日志的时候报错
     */
    @Test
    public void test() throws InterruptedException {
        CountDownLatch latch = new CountDownLatch(1);

        for (int i = 0; i < INT; i++) {
            int finalI = i;
            executor.execute(() -> {
                try {
                    add(finalI);
//                    log.info("{}", finalI);
                } finally {
                    latch.countDown();
                }
            });
        }

        latch.await();

//        Thread.sleep(2000);

       log.info("integer:{}",integer.get());
    }


    /***
     * AtomicReference     Reference
     */
    @Test
    public void test2() throws InterruptedException {

        /// true
        reference.compareAndSet(0, 3);
        /// false
        reference.compareAndSet(2, 4);
        /// true
        reference.compareAndSet(3, 5);
        System.out.println(reference.get());

    }


    /**
     * ReentrantLock 重入锁
     */
    @Test
    public void test3() {
        ReentrantLock lock = new ReentrantLock();

        for (int i = 0; i < INT; i++) {
            executor.execute(() -> {
                try {
                    lock.lock();
///                   count = count + 1;
                    count++;
                } finally {
                    lock.unlock();
                }


            });
        }
        System.out.println(count);
    }

    /**
     * Semaphore  信号量 限流
     * 打印log报错
     */
    @Test
    public void test4() throws InterruptedException {
        Semaphore semaphore = new Semaphore(6);
        CountDownLatch countDownLatch = new CountDownLatch(INT);
        for (int i = 0; i < INT; i++) {
            int finalI = i;
            executor.execute(() -> {
                try {

                    semaphore.acquire();
                    add(1);
//                    semaphore(finalI);
                    semaphore.release();
                } catch (InterruptedException e) {
                    log.info("exception:{}",e);
                } finally {
                    countDownLatch.countDown();
                }
            });
        }
        countDownLatch.await();
        log.info("integer值:{}",integer.get());
    }

    public void semaphore(int i) throws InterruptedException {
        log.info("{}", i);
        Thread.sleep(1000);
    }

    public void add(int i) {
        integer.incrementAndGet();
//        log.info("第{}线程",i);

    }
}
